Passed
Pull Request — master (#181)
by
unknown
03:04
created

local-file.test.ts ➔ isUrl   A

Complexity

Conditions 2

Size

Total Lines 8
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
1
import 'async';
2
import 'assert';
3
import 'should';
4
import fs from 'fs';
5
import path from 'path';
6
import zlib from 'zlib';
7
import { fileURLToPath } from 'url';
8
9
const __filename = fileURLToPath(import.meta.url);
10
const __dirname = path.dirname(__filename);
11
12
// Simple function to validate URLs using the URL object
13
function isUrl(url: string): boolean {
14
  try {
15
    new URL(url);
16
    return true;
17
  } catch {
18
    return false;
19
  }
20
}
21
22
import Sitemapper from '../../lib/assets/sitemapper.js';
23
import { SitemapperResponse } from '../../sitemapper';
24
let sitemapper: Sitemapper;
25
26
describe('Local File Parsing', function () {
27
  beforeEach(() => {
28
    sitemapper = new Sitemapper();
29
  });
30
31
  describe('isLocalFile method', function () {
32
    it('should return false for HTTP URLs', () => {
33
      sitemapper.isLocalFile('http://example.com/sitemap.xml').should.be.false;
34
    });
35
36
    it('should return false for HTTPS URLs', () => {
37
      sitemapper.isLocalFile('https://example.com/sitemap.xml').should.be.false;
38
    });
39
40
    it('should return false for non-existent file paths', () => {
41
      sitemapper.isLocalFile('/non/existent/file.xml').should.be.false;
42
    });
43
44
    it('should return true for existing local files', () => {
45
      const testFile = path.join(__dirname, 'test-sitemap.xml');
46
      sitemapper.isLocalFile(testFile).should.be.true;
47
    });
48
49
    it('should return false for empty or null input', () => {
50
      sitemapper.isLocalFile('').should.be.false;
51
      sitemapper.isLocalFile(null as any).should.be.false;
52
      sitemapper.isLocalFile(undefined as any).should.be.false;
53
    });
54
  });
55
56
  describe('Local sitemap file parsing', function () {
57
    it('should parse a local sitemap.xml file', function (done) {
58
      const testFile = path.join(__dirname, 'test-sitemap.xml');
59
      sitemapper
60
        .fetch(testFile)
61
        .then((data) => {
62
          data.sites.should.be.Array;
63
          data.url.should.equal(testFile);
64
          data.sites.length.should.equal(3);
65
          data.sites.should.containEql('https://example.com/');
66
          data.sites.should.containEql('https://example.com/page1');
67
          data.sites.should.containEql('https://example.com/page2');
68
          data.sites.forEach((site) => {
69
            isUrl(site as string).should.be.true;
70
          });
71
          done();
72
        })
73
        .catch((error) => {
74
          console.error('Test failed:', error);
75
          done(error);
76
        });
77
    });
78
79
    it('should handle local sitemapindex files', function (done) {
80
      const testFile = path.join(__dirname, 'test-sitemap-index.xml');
81
      sitemapper
82
        .fetch(testFile)
83
        .then((data) => {
84
          data.sites.should.be.Array;
85
          data.url.should.equal(testFile);
86
          // Note: This will attempt to fetch the child sitemaps as URLs
87
          // which may fail, but the structure should be parsed
88
          done();
89
        })
90
        .catch((error) => {
91
          console.error('Test failed:', error);
92
          done(error);
93
        });
94
    });
95
96
    it('should work with fields option for local files', function (done) {
97
      const testFile = path.join(__dirname, 'test-sitemap.xml');
98
      const sitemapperWithFields = new Sitemapper({
99
        fields: {
100
          loc: true,
101
          lastmod: true,
102
          priority: true,
103
          changefreq: true,
104
        },
105
      });
106
      
107
      sitemapperWithFields
108
        .fetch(testFile)
109
        .then((data) => {
110
          data.sites.should.be.Array;
111
          data.sites.length.should.equal(3);
112
          
113
          const firstSite = data.sites[0] as any;
114
          firstSite.should.have.property('loc').which.is.a.String();
115
          firstSite.should.have.property('lastmod').which.is.a.String();
116
          firstSite.should.have.property('priority').which.is.a.String();
117
          firstSite.should.have.property('changefreq').which.is.a.String();
118
          
119
          firstSite.loc.should.equal('https://example.com/');
120
          firstSite.priority.should.equal('1.0');
121
          firstSite.changefreq.should.equal('monthly');
122
          
123
          done();
124
        })
125
        .catch((error) => {
126
          console.error('Test failed:', error);
127
          done(error);
128
        });
129
    });
130
131
    it('should handle lastmod filtering for local files', function (done) {
132
      const testFile = path.join(__dirname, 'test-sitemap.xml');
133
      // Set lastmod to a timestamp after 2023-01-02
134
      const sitemapperWithLastmod = new Sitemapper({
135
        lastmod: new Date('2023-01-02T12:00:00+00:00').getTime(),
136
      });
137
      
138
      sitemapperWithLastmod
139
        .fetch(testFile)
140
        .then((data) => {
141
          data.sites.should.be.Array;
142
          // Should only include URLs with lastmod >= 2023-01-02T12:00:00
143
          data.sites.length.should.equal(1); // Only page2 qualifies
144
          data.sites.should.containEql('https://example.com/page2');
145
          done();
146
        })
147
        .catch((error) => {
148
          console.error('Test failed:', error);
149
          done(error);
150
        });
151
    });
152
153
    it('should handle exclusions for local files', function (done) {
154
      const testFile = path.join(__dirname, 'test-sitemap.xml');
155
      const sitemapperWithExclusions = new Sitemapper({
156
        exclusions: [/page1/],
157
      });
158
      
159
      sitemapperWithExclusions
160
        .fetch(testFile)
161
        .then((data) => {
162
          data.sites.should.be.Array;
163
          data.sites.length.should.equal(2);
164
          data.sites.should.containEql('https://example.com/');
165
          data.sites.should.containEql('https://example.com/page2');
166
          data.sites.should.not.containEql('https://example.com/page1');
167
          done();
168
        })
169
        .catch((error) => {
170
          console.error('Test failed:', error);
171
          done(error);
172
        });
173
    });
174
175
    it('should handle non-existent local files gracefully', function (done) {
176
      const nonExistentFile = path.join(__dirname, 'non-existent.xml');
177
      sitemapper
178
        .fetch(nonExistentFile)
179
        .then((data) => {
180
          data.sites.should.be.Array;
181
          data.sites.length.should.equal(0);
182
          data.errors.should.be.Array;
183
          data.errors.length.should.be.greaterThan(0);
184
          done();
185
        })
186
        .catch((error) => {
187
          console.error('Test failed:', error);
188
          done(error);
189
        });
190
    });
191
192
    it('should handle gzipped local files', function (done) {
193
      // Create a gzipped version of the test sitemap
194
      const testFile = path.join(__dirname, 'test-sitemap.xml');
195
      const gzippedFile = path.join(__dirname, 'test-sitemap.xml.gz');
196
      
197
      const content = fs.readFileSync(testFile);
198
      const gzippedContent = zlib.gzipSync(content);
199
      fs.writeFileSync(gzippedFile, gzippedContent);
200
      
201
      sitemapper
202
        .fetch(gzippedFile)
203
        .then((data) => {
204
          data.sites.should.be.Array;
205
          data.sites.length.should.equal(3);
206
          data.sites.should.containEql('https://example.com/');
207
          data.sites.should.containEql('https://example.com/page1');
208
          data.sites.should.containEql('https://example.com/page2');
209
          
210
          // Clean up
211
          fs.unlinkSync(gzippedFile);
212
          done();
213
        })
214
        .catch((error) => {
215
          // Clean up even on failure
216
          if (fs.existsSync(gzippedFile)) {
217
            fs.unlinkSync(gzippedFile);
218
          }
219
          console.error('Test failed:', error);
220
          done(error);
221
        });
222
    });
223
  });
224
});